import React, { Component } from "react";
// import React, { PureComponent } from "react";
import Child from "./Child";

// 只有类组件可以定义自己的生命周期
// PureComponent相当于帮助我们做了shouldComponentUpdate
// 它能够监听所有的数据，包括了对象和数组是否发生了改变
class App extends Component {
  //! 1. 初始化阶段
  // constructor就是组件的第一个生命周期
  // constructor比较特殊的函数，在构造函数被实例化的时候调用，最先调用的，只调用一次
  constructor(props) {
    // 设置state和props等
    // 定义state，改变事件的this指向，定义ref等
    // constructor可以接受一个props作为参数，可以用接受到的props的值作为state的初始值
    super(props);
    this.state = {
      count: 10,
      name: "tom",
      // age: props.age,
      list: [],
      show: true,
    };
    console.log("constructor");
    // this.xxx = this.xxx.bind(this);
    // this.ipt = createRef();
  }

  //! 2. 挂载阶段
  // componentWillMount已经被改名了(16.3版本之后弃用了)
  UNSAFE_componentWillMount() {
    console.log("componentWillMount");
    // 可以改变数据，但是没有必要
    // this.setState({
    //   name: "jerry",
    // });

    // 不能在这里请求数据
    // 因为在16版本的时候新增了一个fiber算法
    // 当组件进行渲染或者进行更新的时候，那么就会去加载文件，解析代码，执行生命周期，渲染页面等等
    // 当组件比较大的时候，那么整个过程就会非常长。js是单线程的，并且上面的过程是同步的。所以有可能会出现页面的卡顿。
    // fiber算法就是将我们的上面的大的任务进行分片化，将一个大的任务分成很多个小任务。执行任务的总时间不会缩短，但是在执行小任务的中间就可以有机会执行其他任务了，就可以缓解页面的卡顿

    // 在这里请求数据的时候，有一定的几率会使请求发送多次，影响性能了
    // 只能在挂载结束以后去请求
    // fetch("http://www.pudge.wang:3080/api/rated/list")
    //   .then((response) => response.json())
    //   .then((res) => {
    //     // console.log(res);
    //     this.setState({
    //       list: res.result,
    //     });
    //   });
  }

  fn = () => {
    this.setState({
      show: false,
    });
  };

  // render本身也是一个生命周期，render必须要有的，必须要return一段jsx代码
  // 最常见的就是添加一些解构和修改数据
  // 因为fiber在这里还没有结束，render里面也不能请求数据
  render() {
    console.log("render");
    const { count, name } = this.state;
    // const {age} = this.props;
    // const nameName = cx({})
    return (
      <>
        <h2>老版(16.3之前)生命周期</h2>
        <div>count: {count}</div>
        <div>name: {name}</div>
        {/* <ul>
          {this.state.list.map((item) => (
            <li key={item._id}>{item.title}</li>
          ))}
        </ul> */}

        <hr />

        <button onClick={this.fn}>btn</button>
        {this.state.show && <Child name={this.state.name} />}
      </>
    );
  }

  componentDidMount() {
    // 相当于vue的mounted，组件挂载结束
    // 这里什么都能做
    console.log("componentDidMount");
    setTimeout(() => {
      this.setState({
        // name: "jerry",
        name: "tom",
      });
    }, 2000);
  }

  //! 更新阶段
  //! state的更新
  // shouldComponentUpdate必须要返回true或者false
  // 无论数据是否发生了改变，只要setState触发，就会重新render
  // 性能优化，特定的时候我们需要去手动返回false，避免不必要的重新渲染
  // shouldComponentUpdate可以接受两个参数

  // shouldComponentUpdate(nextProps, nextState) {
  //   console.log("shouldComponentUpdate");
  //   // return false;
  //   // if (nextState.name === this.state.name) {
  //   //   return false;
  //   // } else {
  //   //   return true;
  //   // }
  //   return nextState.name !== this.state.name;
  // }

  // 被废弃了
  // 相当于vue的beforeUpdate
  // 也做不了什么事情
  UNSAFE_componentWillUpdate() {
    console.log("componentWillUpdate");
  }

  // 相当于vue的updated
  // 在更新以后调用，不能在这里去修改数据，会造成死循环
  componentDidUpdate() {
    console.log("componentDidUpdate");
    // this.setState((prevState) => {
    //   return {
    //     count: prevState.count + 1,
    //   };
    // });
  }
}

export default App;
